/**
 * Watcher类的实现，它负责监听Vue实例上的数据变化，并在变化时执行指定的回调函数。
 * Watcher类通过收集依赖（即数据变化时会通知watcher的数据对象），
 * 并在数据变化时更新自身的值和执行回调，从而实现了响应式的数据绑定。
 * 代码中包含了错误处理、深度监听、懒执行、同步执行等特性，以及用于调试的钩子函数和属性。
 */
import {
  warn,
  remove,
  isObject,
  parsePath,
  _Set as Set,
  handleError,
  invokeWithErrorHandling,
  noop,
  isFunction
} from '../util/index'

import { traverse } from './traverse'
import { queueWatcher } from './scheduler'
import Dep, { pushTarget, popTarget, DepTarget } from './dep'
import { DebuggerEvent, DebuggerOptions } from 'v3/debug'

import type { SimpleSet } from '../util/index'
import type { Component } from 'types/component'
import { activeEffectScope, recordEffectScope } from 'v3/reactivity/effectScope'
// 初始化一个唯一的ID生成器
let uid = 0

/**
 * @internal
 */
// 定义Watcher的选项接口，继承自DebuggerOptions
export interface WatcherOptions extends DebuggerOptions {
  deep?: boolean // 是否深度监听
  user?: boolean // 是否是用户定义的watcher
  lazy?: boolean // 是否是懒执行watcher
  sync?: boolean // 是否同步执行
  before?: Function // 执行前的钩子函数
}

/**
 * A watcher parses an expression, collects dependencies,
 * and fires callback when the expression value changes.
 * This is used for both the $watch() api and directives.
 * 观察者解析表达式，收集依赖项，并在表达式值改变时触发回调。这用于$watch() api和directives。
 * @internal
 */
// 定义Watcher类，实现DepTarget接口
export default class Watcher implements DepTarget {
  // 类的属性定义
  vm?: Component | null // 关联的Vue组件实例
  expression: string // 监听的表达式字符串
  cb: Function // 回调函数
  id: number // 唯一ID
  deep: boolean // 是否深度监听
  user: boolean // 是否是用户定义的watcher
  lazy: boolean // 是否是懒执行watcher
  sync: boolean // 是否同步执行
  dirty: boolean // 标记lazy watcher是否需要重新求值
  active: boolean // 标记watcher是否激活
  deps: Array<Dep> // 存储依赖的Dep对象数组
  newDeps: Array<Dep> // 存储新收集的Dep对象数组
  depIds: SimpleSet // 存储已收集的依赖ID
  newDepIds: SimpleSet // 存储新收集的依赖ID
  before?: Function // 执行前的钩子函数
  onStop?: Function // 停止时的钩子函数
  noRecurse?: boolean // 是否禁止递归
  getter: Function // 用于获取值的getter函数
  value: any // 当前值
  post: boolean // 标记是否在post队列中
  // dev only属性，用于调试
  onTrack?: ((event: DebuggerEvent) => void) | undefined
  onTrigger?: ((event: DebuggerEvent) => void) | undefined

  constructor(
    vm: Component | null,
    expOrFn: string | (() => any),
    cb: Function,
    options?: WatcherOptions | null,
    isRenderWatcher?: boolean
  ) {
    // 记录当前watcher的作用域
    recordEffectScope(
      this,
      // if the active effect scope is manually created (not a component scope),
      // prioritize it
      //如果激活的效果范围是手动创建的（不是一个组件范围），优先级为它
      activeEffectScope && !activeEffectScope._vm
        ? activeEffectScope
        : vm
        ? vm._scope
        : undefined
    )
    // 如果是Vue组件实例且是渲染watcher，则将当前watcher设为组件的_watcher
    if ((this.vm = vm) && isRenderWatcher) {
      vm._watcher = this
    }
    // options
    // 初始化选项
    if (options) {
      this.deep = !!options.deep
      this.user = !!options.user
      this.lazy = !!options.lazy
      this.sync = !!options.sync
      this.before = options.before
      if (__DEV__) {
        this.onTrack = options.onTrack
        this.onTrigger = options.onTrigger
      }
    } else {
      this.deep = this.user = this.lazy = this.sync = false
    }
    // 初始化其他属性
    this.cb = cb
    this.id = ++uid // 生成唯一ID
    this.active = true
    this.post = false
    this.dirty = this.lazy // lazy watcher初始化为true
    this.deps = []
    this.newDeps = []
    this.depIds = new Set()
    this.newDepIds = new Set()
    this.expression = __DEV__ ? expOrFn.toString() : ''
    // parse expression for getter
    // 解析表达式为getter函数
    if (isFunction(expOrFn)) {
      this.getter = expOrFn
    } else {
      this.getter = parsePath(expOrFn)
      if (!this.getter) {
        this.getter = noop
        __DEV__ &&
        /**
         * ${expOrFn} Watcher只接受简单的点分隔路径。要完全控制，请使用函数。
         */
          warn(
            `Failed watching path: "${expOrFn}" ` +
              'Watcher only accepts simple dot-delimited paths. ' +
              'For full control, use a function instead.',
            vm
          )
      }
    }
    // 如果是lazy watcher，则不立即求值，否则调用get方法求值
    this.value = this.lazy ? undefined : this.get()
  }

  /**
   * Evaluate the getter, and re-collect dependencies.
   * // 获取当前值并重新收集依赖
   */
  get() {
    pushTarget(this)  // 将当前watcher设为依赖收集的目标
    let value
    const vm = this.vm
    try {
      value = this.getter.call(vm, vm)  // 执行getter函数获取值
    } catch (e: any) {
      if (this.user) {
        // 用户定义的watcher捕获错误
        handleError(e, vm, `getter for watcher "${this.expression}"`)
      } else {
        // 非用户定义的watcher直接抛出错误
        throw e
      }
    } finally {
      // "touch" every property so they are all tracked as
      // dependencies for deep watching
      // 如果是深度监听，则遍历获取的值以收集所有依赖
      if (this.deep) {
        traverse(value)
      }
      popTarget() // 将当前watcher从依赖收集的目标中移除
      this.cleanupDeps() // 清理依赖
    }
    return value
  }

  /**
   * Add a dependency to this directive.
   * // 添加依赖
   */
  addDep(dep: Dep) {
    const id = dep.id
    if (!this.newDepIds.has(id)) {
      this.newDepIds.add(id)
      this.newDeps.push(dep)
      if (!this.depIds.has(id)) {
        dep.addSub(this) // 添加当前watcher为dep的订阅者
      }
    }
  }

  /**
   * Clean up for dependency collection.
   * 清理依赖
   */
  cleanupDeps() {
    let i = this.deps.length
    while (i--) {
      const dep = this.deps[i]
      if (!this.newDepIds.has(dep.id)) {
        dep.removeSub(this) // 从dep的订阅者列表中移除当前watcher
      }
    }
    // 交换新旧依赖数组和集合，并清空新的集合和数组
    let tmp: any = this.depIds
    this.depIds = this.newDepIds
    this.newDepIds = tmp
    this.newDepIds.clear()
    tmp = this.deps
    this.deps = this.newDeps
    this.newDeps = tmp
    this.newDeps.length = 0
  }

  /**
   * Subscriber interface.
   * Will be called when a dependency changes.
   * 当依赖变化时调用
   */
  update() {
    /* istanbul ignore else */
    // 标记为需要重新求值
    if (this.lazy) {
      this.dirty = true
    } else if (this.sync) {
      this.run() // 同步执行
    } else {
      queueWatcher(this)  //// 异步执行，加入调度队列
    }
  }

  /**
   * Scheduler job interface.
   * Will be called by the scheduler.
   */
  run() {
     // 检查Watcher是否处于激活状态
    if (this.active) {
      // 获取当前Watcher所观察的数据的值
      const value = this.get()
      if (
        // 判断值是否变化，或者值是否为对象/数组（因为对象和数组可能内部变化但引用不变），
        // 或者是否开启了深度观察
        value !== this.value ||
        // Deep watchers and watchers on Object/Arrays should fire even
        // when the value is the same, because the value may
        // have mutated.
        isObject(value) ||
        this.deep
      ) {
        // set new value
        // 更新旧值和新值
        const oldValue = this.value
        this.value = value
        // 如果Watcher是用户定义的，则使用带有错误处理的调用方式执行回调
        if (this.user) {
          const info = `callback for watcher "${this.expression}"`
          invokeWithErrorHandling(
            this.cb,
            this.vm,
            [value, oldValue],
            this.vm,
            info
          )
        } else {
          // 否则直接调用回调
          this.cb.call(this.vm, value, oldValue)
        }
      }
    }
  }

  /**
   * Evaluate the value of the watcher.
   * This only gets called for lazy watchers.
   * // 更新Watcher的值，并标记（即已评估）
   */
  evaluate() {
    this.value = this.get()
    this.dirty = false
  }

  /**
   * Depend on all deps collected by this watcher.
   * 取决于这个观察者收集的所有深度（依赖）。
   */
  depend() {
    // 遍历Watcher的所有依赖，并调用它们的depend方法
    let i = this.deps.length
    while (i--) {
      this.deps[i].depend()
    }
  }

  /**
   * Remove self from all dependencies' subscriber list.
   * 从所有依赖项的订阅者列表中删除自身。
   */
  teardown() {
    // 如果Vue实例存在且未被销毁，则从Vue实例的作用域效果列表中移除当前Watcher
    if (this.vm && !this.vm._isBeingDestroyed) {
      remove(this.vm._scope.effects, this)
    }
    // 如果Watcher处于激活状态，则遍历其所有依赖，并从每个依赖的订阅者列表中移除当前Watcher
    if (this.active) {
      let i = this.deps.length
      while (i--) {
        this.deps[i].removeSub(this)
      }
       // 将Watcher标记为非激活状态
      this.active = false
      // 如果定义了onStop回调，则调用它
      if (this.onStop) {
        this.onStop()
      }
    }
  }
}
